package orchestration.utils;

import java.util.HashMap;
import java.util.Map;

import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.util.Log;

import orchestration.android.execution.tasks.AidlFile;
import orchestration.businessprocess.model.BPAnnotation;
import orchestration.persistence.exceptions.MalformedAnnotationException;

public class AnnotationUtils {
	private static final String TAG="AnnotationUtils";
	
	public static final String INTENT_SOURCE="intent";
	public static final String INTENT_ACTION="action";
	public static final String INTENT_URI="dataUri";
	public static final String INTENT_CATEGORIES="categories";
	private static final String INTENT_FLAGS = "flags";
	
	public static final String CONTENT_PROVIDER_SOURCE="contentProvider";
	public static final String CONTENT_PROVIDER_URI="uri";
	public static final String CONTENT_PROVIDER_PROJECTION="projection";
	public static final String CONTENT_PROVIDER_WHERE_CLAUSE="whereClause";
	public static final String CONTENT_PROVIDER_WHERE_ARGS="whereArgs";
	public static final String CONTENT_PROVIDER_ORDER="orderBy";
	public static final String CONTENT_PROVIDER_SAVE_OPERATION = "operations";
		
	public static final String ANDROID_INFO_SOURCE="androidInfo";
	public static final String ANDROID_INFO_TASK_TYPE_KEY="type";
	public static final String ANDROID_INFO_MAPPINGS="mappings";
	public static final String ANDROID_INFO_TASK_TYPE_ACTIVITY="Activity";
	public static final String ANDROID_INFO_TASK_TYPE_START_SERVICE="Service (Start)";
	public static final String ANDROID_INFO_TASK_TYPE_STOP_SERVICE="Service (Stop)";
	public static final String ANDROID_INFO_TASK_TYPE_BIND_SERVICE="Service (Bind)";
	public static final String ANDROID_INFO_TASK_TYPE_QUERY_CONTENT_PROVIDER="Content Provider (Query)";
	public static final String ANDROID_INFO_IGNORE_BACK = "ignoreBack";
	public static final String THROWING="isThrowing";
	
	public static final String SERVICE_BIND_SOURCE="serviceBind";
	public static final String SERVICE_BIND_AIDL="aidl";
	public static final String SERVICE_BIND_OPS="operations";



	
	
	
	public static HashMap<String,BPAnnotation> getSource2AnnotationMap(HashMap<String,? extends BPAnnotation> id2annotationMap){
		HashMap<String,BPAnnotation> result= new HashMap<String, BPAnnotation>();
		for(String key : id2annotationMap.keySet()){
			BPAnnotation bpa= id2annotationMap.get(key);
			result.put(bpa.getSource(), bpa);
		}
		return result;
	}
	
	public static String getAndroidTaskType(Map<String,BPAnnotation> source2AnnotationMap){
		return source2AnnotationMap.get(ANDROID_INFO_SOURCE).getDetail(ANDROID_INFO_TASK_TYPE_KEY);
	}	
	
	public static Intent getIntent(Map<String,BPAnnotation> source2AnnotationMap) throws MalformedAnnotationException{
		Intent result= new Intent();
		
		//retrieve values
		BPAnnotation intentAnn= source2AnnotationMap.get(INTENT_SOURCE);
		String action= intentAnn.getDetail(INTENT_ACTION);
		String uriString = intentAnn.getDetail(INTENT_URI);		
		String categories= intentAnn.getDetail(INTENT_CATEGORIES);
		String flagString = intentAnn.getDetail(INTENT_FLAGS);
		int flags=0;
		//fill the intent with the retrieved values
		if(action!=null)
			result.setAction(action);
		if(uriString!=null && !uriString.equals(""))
			result.setData(Uri.parse(uriString));
		if(categories!=null && !categories.equals(""))
			for(String cat : categories.split(" "))
				result.addCategory(cat);
		if(flagString!=null && !flagString.equals(""))
			for(String flagName : flagString.split(";"))
				try {
					flags |= Class.forName("android.content.Intent").getDeclaredField(flagName.trim()).getInt(null);
				} catch (Exception e) {
					throw new MalformedAnnotationException(e.getMessage());
				}
		result.addFlags(flags);
		return result;
	}
	public static IntentFilter getIntentFilter(Map<String,BPAnnotation> source2AnnotationMap){
		IntentFilter result= new IntentFilter();
		//retrieve values
		BPAnnotation intentAnn= source2AnnotationMap.get(INTENT_SOURCE);
		String action= intentAnn.getDetail(INTENT_ACTION);
		String uriString = intentAnn.getDetail(INTENT_URI);		
		String categories= intentAnn.getDetail(INTENT_CATEGORIES);
		//TODO test flags!!!!
		//fill the intent with the retrieved values
		if(action!=null)
			for(String singleAction : action.split(";"))
			result.addAction(singleAction);
		if(uriString!=null && !uriString.equals("")){
			Uri uri=Uri.parse(uriString);
			result.addDataScheme(uri.getScheme());
			result.addDataAuthority(uri.getHost(), ""+uri.getPort());
			result.addDataPath(uri.getPath(), 0);
		}
		if(categories!=null && !categories.equals(""))
			for(String cat : categories.split(" "))
				result.addCategory(cat);
		Log.i(TAG, "creating an intentFilter");
		return result;
	}
	public static boolean isThrowing(Map<String,BPAnnotation> source2AnnotationMap){
		return source2AnnotationMap.get(THROWING).getDetail(THROWING).equals("true");
	}

	public static String getContentProviderDetail(
			Map<String, BPAnnotation> source2AnnotationMap,String detailKey) {
		return source2AnnotationMap.get(CONTENT_PROVIDER_SOURCE).getDetail(detailKey);
	}

	public static String getTaskMappings(
			Map<String, BPAnnotation> source2AnnotationMap) {
		return source2AnnotationMap.get(ANDROID_INFO_SOURCE).getDetail(ANDROID_INFO_MAPPINGS);
	}
	
	public static Map<String, String> readMappings(String mappings) {
		Map<String,String> result= new HashMap<String, String>();
		for(String mappingLine : mappings.split(";")){
			String[] singleMappingArray=mappingLine.split("=");
			if(singleMappingArray.length==2){
				result.put(singleMappingArray[0],singleMappingArray[1]);
			}
		}
		return result;
	}
	public static AidlFile getAidlFile(Map<String,BPAnnotation> source2AnnotationMap){
		BPAnnotation bpAnnotation = source2AnnotationMap.get(SERVICE_BIND_SOURCE);
		if(bpAnnotation==null)
			return null;
		String aidlString=bpAnnotation.getDetail(SERVICE_BIND_AIDL);
		if(aidlString==null || aidlString.equals(""))
			return null;
		return AidlFile.parse(aidlString);
	}
	public static String[] getOperationsToCall(Map<String,BPAnnotation> source2AnnotationMap){
		BPAnnotation bpAnnotation = source2AnnotationMap.get(SERVICE_BIND_SOURCE);
		if(bpAnnotation==null)
			return null;
		String operationString=bpAnnotation.getDetail(SERVICE_BIND_OPS);
		if(operationString==null || operationString.equals(""))
			return null;
		return operationString.split(";");
	}
	
}
